package gapidt.analysis.detectors;

import java.util.ArrayList;
import java.util.List;

import gapidt.analysis.APIDesignAnalysisUtils;
import gapidt.analysis.ASTUtils;
import gapidt.analysis.DesignProblem;
import gapidt.analysis.IDesignProblemsDetector;
import gapidt.analysis.designproblems.WhateverMethodParameterType;
import gapidt.analysis.designproblems.WhateverMethodReturnType;
import gapidt.plugin.AnalysisResultsManager;

import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;

public class WhateverTypesDetector extends IDesignProblemsDetector<IMethod> {

	private static String[] whateverTypes = {
		"Object", "java.lang.Object", "Object[]", "java.lang.Object[]",  
		"Vector<Object>", "java.util.Vector<Object>", "Vector<java.lang.Object>", "java.util.Vector<java.lang.Object>", 
		"List<Object>", "java.util.List<Object>", "List<java.lang.Object>", "java.util.List<java.lang.Object>", 
		"Map<Object,Object>", "java.util.Map<Object,Object>", "Map<java.lang.Object,java.lang.Object>", "java.util.Map<java.lang.Object,java.lang.Object>",
		"Collection<Object>", "java.util.Collection<Object>", "Collection<java.lang.Object>", "java.util.Collection<java.lang.Object>",
		"Enumeration<Object>", "java.util.Enumeration<Object>", "Enumeration<java.lang.Object>", "java.util.Enumeration<java.lang.Object>", 
		"Vector", "java.util.Vector",
		"List", "java.util.List", 
		"Map", "java.util.Map",
		"Collection", "java.util.Collection",
		"Enumeration", "java.util.Enumeration"
		}; 
	
	public WhateverTypesDetector(){
		super(IMethod.class);
	}
	
	public static String[] getWhateverTypes() {
		return whateverTypes;
	}

	public static void setWhateverTypes(String[] whateverTypes) {
		WhateverTypesDetector.whateverTypes = whateverTypes;
	}
	
	@Override
	public List<DesignProblem<?>> detectProblems(IMethod method){
		
		List<DesignProblem<?>> designProblems = new ArrayList<DesignProblem<?>>();
		
		if(!APIDesignAnalysisUtils.isServiceMethod(method)){
			return designProblems;
		}
		
		MethodDeclaration methodDeclaration = ASTUtils.parse(method);
		
		for(Object item : methodDeclaration.parameters()){
			SingleVariableDeclaration parameter = (SingleVariableDeclaration) item;
			Type parameterType = parameter.getType();
			
			//6. Analizar tipo de parámetros (WhateverMethodParameterType)
			if(isWhateverType(parameterType)) {
				designProblems.add(new WhateverMethodParameterType(method, parameter.getName().toString(), parameterType.toString()));
				AnalysisResultsManager.getInstance().addDesigProblemCount(getClass().getSimpleName());
			}
		}
		
		if(methodDeclaration.getReturnType2() != null && isWhateverType(methodDeclaration.getReturnType2())){
			designProblems.add(new WhateverMethodReturnType(method));
			AnalysisResultsManager.getInstance().addDesigProblemCount(getClass().getSimpleName());
		}
		
		return designProblems;
	}
	
	protected static boolean isWhateverType(Type type){
		String normalizedTypeName = normalizeTypeName(type.toString());
		for(String whateverType : whateverTypes){
			String normalizedWhateverType = normalizeTypeName(whateverType); 
			if(!normalizedWhateverType.equals("") && normalizedWhateverType.equals(normalizedTypeName))
				return true;
		}
		return false;
	}
	
	private static String normalizeTypeName(String typeName){
		if(typeName != null)
			return typeName.replaceAll(" ", "");
		return "";
	}
}
